/*
* Copyright 2003-2010 Tufts University Licensed under the
* Educational Community License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.osedu.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package tufts.vue;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import tufts.vue.gui.VueButton;
import tufts.vue.propertyeditor.*;
//import fedora.server.types.gen.ComparisonOperator;
//import fedora.server.types.gen.Condition;
/**
* A field:value editor currently specialized for resource properties displayed on
* the object inspector info tab.
*
* @version $Revision: 1.34 $ / $Date: 2010-02-03 19:17:40 $ / $Author: mike $
* @author akumar03
*/
// todo: generalize
public class PropertiesEditor extends JPanel implements DublinCoreConstants {
PropertiesTableModel tableModel;
JTable propertiesTable;
PropertiesSelectionListener sListener;
AddPropertiesButtonListener addPropertiesButtonListener;
DeletePropertiesButtonListener deletePropertiesButtonListener;
JButton addPropertyButton=new VueButton(VueResources.getString("button.add.label"));
JButton deletePropertyButton=new VueButton(VueResources.getString("button.delete.label"));
JLabel questionLabel = new JLabel(VueResources.getImageIcon("smallInfo"), JLabel.LEFT);
/** Creates a new instance of ResourcePropertiesEditor */
public PropertiesEditor(boolean editable) {
tableModel = new PropertiesTableModel(editable);
setResourePropertiesPanel();
}
public PropertiesEditor(PropertyMap properties, boolean editable) {
tableModel = new PropertiesTableModel(properties, editable);
setResourePropertiesPanel();
}
private void setResourePropertiesPanel() {
addPropertyButton.setToolTipText("Add Metadata");
deletePropertyButton.setToolTipText("Delete Metadata");
questionLabel.setToolTipText("Add or delete resource metadata");
// TODO: make table resize with window just like the JTable in the
// NodeFilterEditor.
propertiesTable=new JTable(tableModel);
//propertiesTable.setCellSelectionEnabled(true);
//propertiesTable.setBackground(Color.red);
//propertiesTable.setOpaque(false); // will need to subclass and make transparent the returned renderers
propertiesTable.setPreferredScrollableViewportSize(new Dimension(200,150));
propertiesTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
propertiesTable.getColumnModel().getColumn(0).setPreferredWidth(300);
propertiesTable.getColumnModel().getColumn(1).setPreferredWidth(700);
propertiesTable.addFocusListener(new FocusListener() {
public void focusLost(FocusEvent e) {
if(propertiesTable.isEditing()) {
propertiesTable.getCellEditor(propertiesTable.getEditingRow(),propertiesTable.getEditingColumn()).stopCellEditing();
}
propertiesTable.removeEditor();
}
public void focusGained(FocusEvent e) {
}
});
propertiesTable.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if (propertiesTable.getSelectedRow() == (propertiesTable.getRowCount()-1)
&& e.getKeyCode() == KeyEvent.VK_ENTER && tableModel.isEditable())
{
tableModel.addDefaultProperty();
}
}
});
JScrollPane conditionsScrollPane=new JScrollPane(propertiesTable);
//conditionsScrollPane.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
JPanel propertiesPanel=new JPanel();
propertiesPanel.setLayout(new BorderLayout());
propertiesPanel.add(conditionsScrollPane, BorderLayout.CENTER);
//propertiesPanel.setBorder(BorderFactory.createEmptyBorder(2,0,3,0));
// setting the properties editor for fields
JPanel labelPanel=new JPanel(new BorderLayout());
//labelPanel.setBorder(BorderFactory.createEmptyBorder(3,6,3,6));
JLabel label = new JLabel(VueResources.getString("jlabel.resourcemetadata"));
label.setAlignmentX(Label.LEFT_ALIGNMENT);
labelPanel.add(label,BorderLayout.WEST);
JPanel topPanel=new JPanel(new FlowLayout(FlowLayout.RIGHT,2,0));
//topPanel.setBorder(BorderFactory.createEmptyBorder(3,6,3,6));
//disable buttons if not editable
//System.out.println("Editable: "+tableModel.isEditable());
if(tableModel.isEditable()) {
addPropertyButton.setEnabled(true);
deletePropertyButton.setEnabled(true);
sListener = new PropertiesSelectionListener(deletePropertyButton,-1);
propertiesTable.getSelectionModel().addListSelectionListener(sListener);
addPropertiesButtonListener = new AddPropertiesButtonListener(tableModel);
addPropertyButton.addActionListener(addPropertiesButtonListener);
deletePropertiesButtonListener = new DeletePropertiesButtonListener(propertiesTable,sListener);
deletePropertyButton.addActionListener(deletePropertiesButtonListener);
topPanel.add(addPropertyButton);
topPanel.add(deletePropertyButton);
topPanel.add(questionLabel);
JComboBox comboBox = new JComboBox(DC_FIELDS);
//comboBox.setLightWeightPopupEnabled(true);
propertiesTable.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(comboBox));
} else {
addPropertyButton.setEnabled(false);
deletePropertyButton.setEnabled(false);
}
labelPanel.add(topPanel,BorderLayout.EAST);
// setting the panel for top buttons
// setting box layout
JPanel innerPanel=new JPanel();
innerPanel.setLayout(new BorderLayout());
//innerPanel.setBorder(BorderFactory.createEmptyBorder(0,6,6,6));
innerPanel.add(labelPanel,BorderLayout.NORTH);
innerPanel.add(propertiesPanel,BorderLayout.CENTER);
//innerPanel.add(topPanel);
//innerPanel.setBorder(BorderFactory.createTitledBorder("Metadata"));
setLayout(new BorderLayout());
add(innerPanel,BorderLayout.CENTER);
//setSize(300, 300);
validate();
}
public void setProperties(PropertyMap properties,boolean editable) {
tableModel.setEditable(editable);
tableModel.setProperties(properties);
/*
tableModel = new PropertiesTableModel(properties,editable);
// todo: do NOT set a new table model here: just tell
// the old one to load new data and send a refresh.
// That way user dragged settings of column widths
// aren't blown away every time we display new data.
propertiesTable.setModel(tableModel);
propertiesTable.getColumnModel().getColumn(0).setPreferredWidth(300);
propertiesTable.getColumnModel().getColumn(1).setPreferredWidth(700);
*/
if(tableModel.isEditable()) {
addPropertyButton.setEnabled(true);
deletePropertyButton.setEnabled(true);
sListener = new PropertiesSelectionListener(deletePropertyButton,-1);
propertiesTable.getSelectionModel().addListSelectionListener(sListener);
addPropertyButton.removeActionListener(addPropertiesButtonListener);
addPropertiesButtonListener = new AddPropertiesButtonListener(tableModel);
addPropertyButton.addActionListener(addPropertiesButtonListener);
deletePropertyButton.removeActionListener(deletePropertiesButtonListener);
deletePropertiesButtonListener = new DeletePropertiesButtonListener(propertiesTable,sListener);
deletePropertyButton.addActionListener(deletePropertiesButtonListener);
JComboBox comboBox = new JComboBox(DC_FIELDS);
propertiesTable.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(comboBox));
} else {
addPropertyButton.setEnabled(false);
deletePropertyButton.setEnabled(false);
}
}
public void clear() {
//setProperties(new Properties(), tableModel.isEditable());
//tableModel.setProperties(new Properties());
tableModel.setProperties(new PropertyMap());
}
public PropertiesTableModel getPropertiesTableModel() {
return tableModel;
}
// a model for Properties table
private static String PROPERTY_NOT_SET = "";
public static class PropertiesTableModel extends AbstractTableModel {
java.util.List m_conditions;
Map mProperties;
boolean editable;
public PropertiesTableModel(boolean editable) {
this(new PropertyMap(), editable);
}
public PropertiesTableModel(PropertyMap properties, boolean editable) {
this.editable = editable;
setProperties(properties);
}
public java.util.List getConditions() {
return m_conditions;
}
public Map getProperties() {
return mProperties;
}
public void setProperties(PropertyMap properties) {
m_conditions=new ArrayList();
this.mProperties = properties;
ArrayList keys = new ArrayList(properties.keySet());
Collections.sort(keys);
Iterator i = keys.iterator();
while (i.hasNext()) {
Condition cond = new Condition();
String key = (String) i.next();
cond.setProperty(key);
cond.setOperator(ComparisonOperator.eq);
cond.setValue(properties.getProperty(key));
m_conditions.add(cond);
}
if (isEditable() && m_conditions.size() == 0)
addProperty(DC_FIELDS[0], PROPERTY_NOT_SET);
fireTableDataChanged();
}
public void setEditable(boolean canEdit) {
this.editable = canEdit;
}
public boolean isEditable() {
return editable;
}
public String getColumnName(int col) {
if (col==0) {
return "Field";
} else {
return "Value";
}
}
public int getRowCount() {
return m_conditions.size();
}
public int getColumnCount() {
return 2;
}
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
public Object getValueAt(int row, int col) {
Condition cond=(Condition) m_conditions.get(row);
if (col==0)
return cond.getProperty();
else
return cond.getValue();
}
public void addProperty(String key, String value) {
Condition cond = new Condition();
cond.setProperty(key);
cond.setOperator(ComparisonOperator.eq);
cond.setValue(value);
if (value != PROPERTY_NOT_SET)
mProperties.put(key, value);
m_conditions.add(cond);
fireTableDataChanged();
}
public void addDefaultProperty() {
addProperty(DC_FIELDS[0], PROPERTY_NOT_SET);
}
public boolean isCellEditable(int row, int col) {
//Note that the data/cell address is constant,
//no matter where the cell appears onscreen.
return editable;
}
/*
* Don't need to implement this method unless your table's
* data can change.
*/
public void setValueAt(Object value, int row, int col) {
mProperties.remove(((Condition)m_conditions.get(row)).getProperty());
Condition cond;
if(row == -1)
cond = new Condition();
else
cond = (Condition) m_conditions.get(row);
if(col == 0)
cond.setProperty((String)value);
if(col == 1)
cond.setValue((String)value);
// row = -1 adds new condions else replace the existing one.
if (row==-1)
m_conditions.add(cond);
else
m_conditions.set(row, cond);
//mProperties.setProperty(cond.getProperty(), cond.getValue());
mProperties.put(cond.getProperty(), cond.getValue());
fireTableCellUpdated(row, col);
}
}
public class PropertiesSelectionListener implements ListSelectionListener {
private int m_selectedRow;
private JButton m_deleteButton;
public PropertiesSelectionListener(JButton deleteButton, int selectedRow) {
m_selectedRow=selectedRow;
m_deleteButton=deleteButton;
updateButtons();
}
public void valueChanged(ListSelectionEvent e) {
//Ignore extra messages.
if (e.getValueIsAdjusting()) return;
ListSelectionModel lsm = (ListSelectionModel)e.getSource();
if (lsm.isSelectionEmpty()) {
m_selectedRow=-1;
} else {
m_selectedRow=lsm.getMinSelectionIndex();
}
updateButtons();
}
public int getSelectedRow() {
return m_selectedRow;
}
public void setSelectedRow(int row) {
this.m_selectedRow = row;
}
private void updateButtons() {
if(PropertiesEditor.this.tableModel.isEditable()){
if (getSelectedRow()==-1) {
m_deleteButton.setEnabled(false);
} else {
m_deleteButton.setEnabled(true);
}
}
}
}
public class AddPropertiesButtonListener implements ActionListener {
private PropertiesTableModel m_model;
public AddPropertiesButtonListener(PropertiesTableModel model) {
m_model=model;
}
public void actionPerformed(ActionEvent e) {
m_model.addDefaultProperty();
}
}
public class DeletePropertiesButtonListener implements ActionListener {
private PropertiesSelectionListener m_sListener;
private JTable table;
public DeletePropertiesButtonListener(JTable table,PropertiesSelectionListener sListener) {
this.table = table;
m_sListener=sListener;
}
public void actionPerformed(ActionEvent e) {
// will only be invoked if an existing row is selected
int r=m_sListener.getSelectedRow();
((PropertiesTableModel)table.getModel()).getConditions().remove(r);
((PropertiesTableModel)table.getModel()).fireTableRowsDeleted(r,r);
if(r> 0)
table.setRowSelectionInterval(r-1, r-1);
else if(table.getRowCount() > 0)
table.setRowSelectionInterval(0,0);
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
}
}